﻿using OvenParameterForm.Model;
using OvenParameterForm.Technics;
using OvenParameterForm.Util;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;

namespace OvenParameterForm.Device
{
    public class Oven
    {
        private string OvenName;
        private string str = "OvenParameterForm.Technics.";
        private OvenAndFormula formula;
        List<TechnicsBaseClass> technicsList;
        SqlSugarClientHelp<OvenAndFormula> sqlFormulaDAL = new SqlSugarClientHelp<OvenAndFormula>();
        /// <summary>
        /// 工艺开始或者停止信号
        /// </summary>
        public Action<bool> TechnicsStartAndStopAction;
        /// <summary>
        /// 收到工艺运行时的状态信息
        /// </summary>
        public Action<string> ReceiveTechnicsRunInfoAction;
        /// <summary>
        /// 烘箱状态，当烘箱运行时，不允许更改烘箱配方及调整烘箱等
        /// </summary>
        private bool ovenState = false;
        public Action technicsOverAction;
        public bool OvenState {
            get => ovenState;
            set 
            {
                ovenState = value;
                TechnicsStartAndStopAction(value);                
            }
        }

        /// <summary>
        /// 带参构造函数，用来注入烘箱名
        /// </summary>
        /// <param name="name"></param>
        public Oven(string name)
        {
            OvenName = name;
            technicsList = new List<TechnicsBaseClass>();
        }
        /// <summary>
        /// 打开配方，根据烘箱名打开配方，加载配方
        /// </summary>
        /// <param name="ctr">控件，默认为空，当有控件时，将烘箱名赋值给控件显示</param>
        /// <returns></returns>
        public bool OpenFormula(Control ctr = null)
        {
            if (OvenName != null)
            {
                sqlFormulaDAL.FindFirstByCondition(OvenName, "OvenName", out formula);
                LoadFormula(formula.FormulaPath);
                if (ctr != null) ctr.Text = formula.FormulaPath.SplitLast("\\").SplitFirst(".");
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 加载配方，通过配方地址，加载配方XML，将XML树形文件转化为类存入流程集合中
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public bool LoadFormula(string path)
        {
            try
            {
                technicsList.Clear();
                XDocument xdoc = XDocument.Load(path);
                xdoc.Root.Elements().ForEach(f =>
                {
                    if (f.HasElements)
                    {
                        TechnicsBaseClass te0 = (TechnicsBaseClass)Assembly.Load("OvenParameterForm").CreateInstance(str + f.Name.ToString(), true, BindingFlags.Default, null, new object[] { OvenName }, null, null);
                        technicsList.Add(PublicFunc.XMLToClass(f, te0));
                        te0.sendStatus += TechnicsRunInfo;
                        f.Elements().ForEach((e) =>
                        {
                            TechnicsBaseClass te1 = (TechnicsBaseClass)Assembly.Load("OvenParameterForm").CreateInstance(str + e.Name.ToString(), true, BindingFlags.Default, null, new object[] { OvenName }, null, null);
                            te0.子流程.Add(PublicFunc.XMLToClass(e, te1));
                            te1.sendStatus += TechnicsRunInfo;
                        });
                    }
                    else
                    {
                        TechnicsBaseClass te = (TechnicsBaseClass)Assembly.Load("OvenParameterForm").CreateInstance(str + f.Name.ToString(), true, BindingFlags.Default, null, new object[] { OvenName }, null, null);
                        technicsList.Add(PublicFunc.XMLToClass(f, te));
                        te.sendStatus += TechnicsRunInfo;
                    }
                });
                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 启动工艺，当流程类不为空时，另起任务安装顺序执行流程集合，将烘箱状态置on，流程集合结束后烘箱状态置off
        /// </summary>
        public  void StartTechnics()
        {
            if (technicsList.Count > 0 && !ovenState)
            {
               
               Task task=new Task(() =>
                {
                    OvenState = true;
                    technicsList.ForEach(f => f.Run());
                    OvenState = false;
                    TechnicsRunInfo("流程运行结束");
                    technicsOverAction.Invoke();
                });
                task.Start();
            }
            else
            {
                return;
            }

        }
        /// <summary>
        /// 停止工艺，将流程集合中的每个停止信号都置on
        /// </summary>
        public  void StopTechnics()
        {
                Task t=new Task(() =>
                {
                    technicsList.ForEach(f =>
                    {
                        if (f.子流程.Count > 0)
                        {
                            f.子流程.ForEach(e => e.flagStopTechnics = true); ;
                        }
                        f.flagStopTechnics = true;
                    });
                    OvenState = false;
                    //TechnicsRunInfo("流程已停止");
                    technicsOverAction.Invoke();
                });  
            t.Start();
        }
        public string TechnicsRunInfo(string str)
        {
            ReceiveTechnicsRunInfoAction(str);
            return str;
        }
    }
}
